import tkinter as tk
from tkinter import ttk
from tkinter import OptionMenu
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from Student import StudentManagementSystem

# 设置中文字体为黑体（SimHei）
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family'] = 'sans-serif'


class App:
    def __init__(self, root, sms):
        self.root = root
        self.sms = sms
        self.conn = sms.conn  # 获取数据库连接
        self.root.title("学生成绩可视化系统")
        self.root.geometry("800x600")
        self.root.resizable(False, False)

        self.create_sidebar()
        self.create_content()
        self.current_showing_frame = None

    def create_sidebar(self):
        sidebar = tk.Frame(self.root, width=200, height=400, bg="lightgray")
        sidebar.pack(side=tk.LEFT, fill=tk.Y)

        add_student_btn = tk.Button(sidebar, text="添加学生", command=self.show_add_student)
        add_student_btn.pack(pady=10)

        add_grade_btn = tk.Button(sidebar, text="添加成绩", command=self.show_add_grade)
        add_grade_btn.pack(pady=10)

        view_student_info_btn = tk.Button(sidebar, text="学生信息", command=self.show_view_student_info)
        view_student_info_btn.pack(pady=10)

        view_student_grade_classification_btn = tk.Button(sidebar, text="学生成绩分类",
                                                          command=self.show_student_grade_classification)
        view_student_grade_classification_btn.pack(pady=10)

        visualize_grade_btn = tk.Button(sidebar, text="成绩可视化", command=self.show_visualize_grade)
        visualize_grade_btn.pack(pady=10)


        exit_btn = tk.Button(sidebar, text="退出", command=self.root.quit)
        exit_btn.pack(pady=10)

    def show_student_grade_classification(self):
        """
        展示指定学号学生成绩分类情况的界面交互逻辑
        """
        self.hide_current_frame()
        self.current_showing_frame = self.student_grade_classification_frame()
        self.current_showing_frame.pack()

    def student_grade_classification_frame(self):
        frame = tk.Frame(self.content)
        tk.Label(frame, text="请输入学号:").grid(row=0, column=0, pady=5)
        student_id_entry = tk.Entry(frame)
        student_id_entry.grid(row=0, column=1, pady=5)

        tk.Button(frame, text="查询",
                  command=lambda: self.display_student_grade_classification(student_id_entry.get())).grid(row=1,
                                                                                                          column=0,
                                                                                                          columnspan=2,
                                                                                                          pady=10)
        return frame

    def display_student_grade_classification(self, student_id):
        """
        根据输入学号，获取并展示学生成绩分类情况（调用StudentManagementSystem的方法并展示表格结果）
        """
        try:
            student_name = self.sms.get_student_name_by_id(student_id)
            passed_table, failed_table = self.sms.get_student_grade_table_by_id(student_id)
            if (passed_table or failed_table):
                self.show_grade_table_in_new_window(passed_table, failed_table, student_name)
            else:
                self.show_error(f"未找到学号为 {student_id} 的学生成绩信息")
        except ValueError as e:
            self.show_error(str(e))

    def show_grade_table_in_new_window(self, passed_table, failed_table, student_name):
        """
        在新窗口展示成绩表格结果，并显示学生姓名，将及格和不及格分别展示
        """
        new_window = tk.Toplevel(self.root)
        tk.Label(new_window, text=f"学生姓名: {student_name}", font=("SimHei", 12)).pack(pady=5)

        # 展示及格成绩表格
        if passed_table:
            passed_tree = ttk.Treeview(new_window, columns=("课程", "成绩", "是否及格"), show="headings")
            passed_tree.heading("课程", text="课程")
            passed_tree.heading("成绩", text="成绩")
            passed_tree.heading("是否及格", text="是否及格")
            for row in passed_table:
                passed_tree.insert("", tk.END, values=row)
            passed_tree.pack()

        # 展示不及格成绩表格
        if failed_table:
            failed_tree = ttk.Treeview(new_window, columns=("课程", "成绩", "是否及格"), show="headings")
            failed_tree.heading("课程", text="课程")
            failed_tree.heading("成绩", text="成绩")
            failed_tree.heading("是否及格", text="是否及格")
            for row in failed_table:
                failed_tree.insert("", tk.END, values=row)
            failed_tree.pack()

    def create_content(self):
        self.content = tk.Frame(self.root)
        self.content.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

    def show_add_student(self):
        self.hide_current_frame()
        self.current_showing_frame = self.add_student_frame()
        self.current_showing_frame.pack()

    def add_student_frame(self):
        frame = tk.Frame(self.content)
        tk.Label(frame, text="学号:").grid(row=0, column=0, pady=5)
        student_id_entry = tk.Entry(frame)
        student_id_entry.grid(row=0, column=1, pady=5)

        tk.Label(frame, text="姓名:").grid(row=1, column=0, pady=5)
        name_entry = tk.Entry(frame)
        name_entry.grid(row=1, column=1, pady=5)

        tk.Label(frame, text="班级:").grid(row=2, column=0, pady=5)
        class_id_entry = tk.Entry(frame)
        class_id_entry.grid(row=2, column=1, pady=5)

        tk.Label(frame, text="性别:").grid(row=3, column=0, pady=5)
        gender_entry = tk.Entry(frame)
        gender_entry.grid(row=3, column=1, pady=5)

        tk.Button(frame, text="添加",
                  command=lambda: self.add_student(student_id_entry.get(), name_entry.get(),
                                                   class_id_entry.get(), gender_entry.get())).grid(row=4,
                                                                                                   column=0,
                                                                                                   columnspan=2,
                                                                                                   pady=10)
        return frame

    def add_student(self, student_id, name, class_id, gender):
        try:
            if self.sms.add_student(student_id, name, class_id, gender):
                self.show_message("学生添加成功")
            else:
                self.show_error("学生添加失败，学号可能已存在")
        except ValueError as e:
            self.show_error(str(e))

    def show_add_grade(self):
        self.hide_current_frame()
        self.current_showing_frame = self.add_grade_frame()
        self.current_showing_frame.pack()

    def add_grade_frame(self):
        frame = tk.Frame(self.content)
        tk.Label(frame, text="学号:").grid(row=0, column=0, pady=5)
        student_id_entry = tk.Entry(frame)
        student_id_entry.grid(row=0, column=1, pady=5)

        tk.Label(frame, text="课程:").grid(row=1, column=0, pady=5)

        # 获取所有课程名称
        cursor = self.conn.cursor()
        cursor.execute("SELECT course_name FROM courses")
        courses = [row[0] for row in cursor.fetchall()]

        # 创建课程下拉框使用的变量
        course_var = tk.StringVar(frame)
        course_var.set(courses[0])  # 默认选择第一个课程

        # 创建课程下拉框
        course_menu = OptionMenu(frame, course_var, *courses)
        course_menu.grid(row=1, column=1, pady=5)

        tk.Label(frame, text="成绩:").grid(row=2, column=0, pady=5)
        grade_entry = tk.Entry(frame)
        grade_entry.grid(row=2, column=1, pady=5)

        tk.Button(frame, text="添加",
                  command=lambda: self.add_grade(student_id_entry.get(), course_var.get(), grade_entry.get())).grid(
            row=3,
            column=0,
            columnspan=2,
            pady=10)
        return frame

    def add_grade(self, student_id, course_name, grade):
        try:
            if self.sms.add_grade(student_id, course_name, grade):
                self.show_message("成绩添加成功")
            else:
                self.show_error("成绩添加失败，可能信息有误")
        except ValueError as e:
            self.show_error(str(e))

    def show_view_student_info(self):
        self.hide_current_frame()
        self.current_showing_frame = self.view_student_info_frame()
        self.current_showing_frame.pack()

    def view_student_info_frame(self):
        frame = tk.Frame(self.content)
        tk.Label(frame, text="学号(直接查询查看所有学生):").grid(row=0, column=0, pady=5)
        student_id_entry = tk.Entry(frame)
        student_id_entry.grid(row=0, column=1, pady=5)

        tk.Button(frame, text="查询",
                  command=lambda: self.refresh_student_info(student_id_entry.get())).grid(row=1,
                                                                                         column=0,
                                                                                         columnspan=2,
                                                                                         pady=10)
        return frame

    def refresh_student_info(self, student_id):
        self.hide_current_frame()
        self.current_showing_frame = self.show_student_info(student_id)
        self.current_showing_frame.pack()

    def show_student_info(self, student_id):
        frame = tk.Frame(self.content)

        # 创建Treeview用于展示学生信息，添加滚动条
        tree = ttk.Treeview(frame, columns=("学号", "姓名", "班级", "性别", "课程", "成绩"), show="headings")

        # 设置列标题
        tree.heading("学号", text="学号")
        tree.heading("姓名", text="姓名")
        tree.heading("班级", text="班级")
        tree.heading("性别", text="性别")
        tree.heading("课程", text="课程")
        tree.heading("成绩", text="成绩")

        # 设置列宽
        tree.column("学号", width=100)
        tree.column("姓名", width=100)
        tree.column("班级", width=100)
        tree.column("性别", width=50)
        tree.column("课程", width=150)
        tree.column("成绩", width=100)

        # 创建垂直滚动条并关联到Treeview
        scrollbar = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=tree.yview)
        tree.configure(yscrollcommand=scrollbar.set)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 获取学生信息并插入到Treeview中
        student_info = self.sms.view_student_info(student_id)
        for row in student_info:
            tree.insert("", tk.END, values=row)

        return frame

    def show_visualize_grade(self):
        self.hide_current_frame()
        self.current_showing_frame = self.visualize_grade_frame()
        self.current_showing_frame.pack()

    def visualize_grade_frame(self):
        frame = tk.Frame(self.content)

        # 创建一个变量来存储用户选择
        self.visualize_option = tk.StringVar(frame)
        self.visualize_option.set("请选择")

        # 创建下拉框
        options = ["按学号查看", "按班级查看"]
        option_menu = OptionMenu(frame, self.visualize_option, *options)
        option_menu.grid(row=0, column=0, columnspan=2, pady=5)

        # 创建学号输入框（初始隐藏）
        self.student_id_entry = tk.Entry(frame)
        self.student_id_entry.grid(row=1, column=0, columnspan=2, pady=5)
        self.student_id_entry.grid_remove()  # 初始隐藏

        # 创建班级输入框（初始隐藏）
        self.class_id_entry = tk.Entry(frame)
        self.class_id_entry.grid(row=2, column=0, columnspan=2, pady=5)
        self.class_id_entry.grid_remove()  # 初始隐藏

        # 可视化按钮
        tk.Button(frame, text="可视化", command=self.visualize_grade_with_option).grid(row=3, column=0, columnspan=2,
                                                                                       pady=10)

        # 根据选择显示相应的输入框
        self.visualize_option.trace("w", self.show_correct_entry)

        return frame

    def show_correct_entry(self, *args):
        choice = self.visualize_option.get()
        if choice == "按学号查看":
            self.student_id_entry.grid()
            self.class_id_entry.grid_remove()
        elif choice == "按班级查看":
            self.class_id_entry.grid()
            self.student_id_entry.grid_remove()

    def visualize_grade_with_option(self):
        choice = self.visualize_option.get()
        if choice == "按学号查看":
            student_id = self.student_id_entry.get()
            fig = self.sms.visualize_grade(student_id, None)
        elif choice == "按班级查看":
            class_id = self.class_id_entry.get()
            fig = self.sms.visualize_grade(None, class_id)
        if fig:
            self.show_grade_figure_in_new_window(fig)

    def show_grade_figure_in_new_window(self, fig):
        new_window = tk.Toplevel(self.root)
        canvas = FigureCanvasTkAgg(fig, master=new_window)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

    def show_message(self, message):
        message_window = tk.Toplevel(self.root)
        tk.Label(message_window, text=message).pack(pady=10)
        tk.Button(message_window, text="确定", command=message_window.destroy).pack(pady=10)

    def show_error(self, error_message):
        error_window = tk.Toplevel(self.root)
        tk.Label(error_window, text=error_message, fg="red").pack(pady=10)
        tk.Button(error_window, text="确定", command=error_window.destroy).pack(pady=10)

    def hide_current_frame(self):
        if self.current_showing_frame and self.current_showing_frame.winfo_exists():
            self.current_showing_frame.pack_forget()
            self.current_showing_frame.destroy()
        self.current_showing_frame = None



if __name__ == "__main__":
    sms = StudentManagementSystem('students.db')
    root = tk.Tk()
    app = App(root, sms)
    root.mainloop()